home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / gnu / nethack.lha / nethack-3.1 / src / dothrow.c < prev    next >
C/C++ Source or Header  |  1993-01-24  |  21KB  |  809 lines

  1. /*    SCCS Id: @(#)dothrow.c    3.1    92/12/10    */
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. /* Contains code for 't' (throw) */
  6.  
  7. #include "hack.h"
  8.  
  9. static void FDECL(hitfloor, (struct obj *));
  10. static int FDECL(gem_accept, (struct monst *, struct obj *));
  11. static int FDECL(throw_gold, (struct obj *));
  12. static void FDECL(check_shop_obj, (struct obj *,XCHAR_P,XCHAR_P,BOOLEAN_P));
  13.  
  14. static const char NEARDATA toss_objs[] =
  15.     { ALLOW_COUNT, GOLD_CLASS, ALL_CLASSES, WEAPON_CLASS, 0 };
  16. extern boolean notonhead;    /* for long worms */
  17.  
  18. int
  19. dothrow()
  20. {
  21.     register struct obj *obj;
  22.  
  23.     if(check_capacity(NULL)) return(0);
  24.     obj = getobj(toss_objs, "throw");
  25.     /* it is also possible to throw food */
  26.     /* (or jewels, or iron balls... ) */
  27.  
  28.     if(!obj || !getdir(NULL)) {       /* ask "in what direction?" */
  29.         if (obj && obj->oclass == GOLD_CLASS) {
  30.             u.ugold += obj->quan;
  31.             flags.botl = 1;
  32.             dealloc_obj(obj);
  33.         }
  34.         return(0);
  35.     }
  36.  
  37.     if(obj->oclass == GOLD_CLASS) return(throw_gold(obj));
  38.  
  39.     if(!canletgo(obj,"throw"))
  40.         return(0);
  41.     if (obj->oartifact == ART_MJOLLNIR && obj != uwep) {
  42.         You("must be wielding %s in order to throw it.", xname(obj));
  43.         return(0);
  44.     }
  45.     if ((obj->oartifact == ART_MJOLLNIR && ACURR(A_STR) != 125)
  46.        || (obj->otyp == BOULDER
  47. #ifdef POLYSELF
  48.                     && !throws_rocks(uasmon)
  49. #endif
  50.                                 )) {
  51.         pline("It's too heavy.");
  52.         return(1);
  53.     }
  54.     if(!u.dx && !u.dy && !u.dz) {
  55.         You("cannot throw an object at yourself.");
  56.         return(0);
  57.     }
  58.     u_wipe_engr(2);
  59.  
  60.     if(obj == uwep) {
  61.         if(welded(obj)) {
  62.         weldmsg(obj, FALSE);
  63.         return(1);
  64.         }
  65.         if(obj->quan > 1L)
  66.         setuwep(splitobj(obj, 1L));
  67.         else {
  68.         setuwep((struct obj *)0);
  69.         if (uwep) return(1); /* unwielded, died, rewielded */
  70.         }
  71.     }
  72.     else if(obj->quan > 1L)
  73.         (void) splitobj(obj, 1L);
  74.     freeinv(obj);
  75.     return(throwit(obj));
  76. }
  77.  
  78. static void
  79. hitfloor(obj)
  80. register struct obj *obj;
  81. {
  82.     if (IS_SOFT(levl[u.ux][u.uy].typ) || u.uinwater) {
  83.         dropy(obj);
  84.         if(*u.ushops)
  85.             check_shop_obj(obj, obj->ox, obj->oy, FALSE);
  86.         return;
  87.     }
  88.     if (IS_ALTAR(levl[u.ux][u.uy].typ)) doaltarobj(obj);
  89.     else
  90.         pline("%s hits the floor.", Doname2(obj));
  91.     if (breaks(obj, TRUE)) return;
  92.     else if(obj->oclass == POTION_CLASS) {
  93.         pline("The flask breaks, and you smell a peculiar odor...");
  94.         potionbreathe(obj);
  95.         if(*u.ushops)
  96.             check_shop_obj(obj, u.ux, u.uy, TRUE);
  97.         obfree(obj, (struct obj *)0);
  98.     } else {
  99.         if(ship_object(obj, u.ux, u.uy, FALSE)) 
  100.             return;
  101.         dropy(obj);
  102.         if(*u.ushops)
  103.             check_shop_obj(obj, obj->ox, obj->oy, FALSE);
  104.     }
  105. }
  106.  
  107. /*
  108.  * The player moves through the air for a few squares as a result of
  109.  * throwing or kicking something.  To simplify matters, bumping into monsters
  110.  * won't cause damage but will wake them and make them angry.
  111.  * Auto-pickup isn't done, since you don't have control over your movements
  112.  * at the time.
  113.  * dx and dy should be the direction of the hurtle, not of the original
  114.  * kick or throw.
  115.  */
  116. void
  117. hurtle(dx, dy, range)
  118.     int dx, dy, range;
  119. {
  120.     register struct monst *mon;
  121.     struct obj *obj;
  122.     int nx, ny;
  123.  
  124.     if(!range || (!dx && !dy) || u.ustuck) return; /* paranoia */
  125.  
  126.     nomul(-range);
  127.     You("%s in the opposite direction.", range > 1 ? "hurtle" : "float");
  128.     while(range--) {
  129.     nx = u.ux + dx;
  130.     ny = u.uy + dy;
  131.  
  132.     if(!isok(nx,ny)) break;
  133.     if(IS_ROCK(levl[nx][ny].typ) || closed_door(nx,ny)) {
  134.         pline("Ouch!");
  135.         losehp(rnd(2+range), IS_ROCK(levl[nx][ny].typ) ?
  136.            "bumping to a wall" : "bumping into a door", KILLED_BY);
  137.         break;
  138.     }
  139.  
  140.     if (obj = sobj_at(BOULDER,nx,ny)) {
  141.         You("bump into a %s.  Ouch!", xname(obj));
  142.         losehp(rnd(2+range), "bumping to a boulder", KILLED_BY);
  143.         break;
  144.     }
  145.  
  146.     u.ux = nx;
  147.     u.uy = ny;
  148.     newsym(u.ux - dx, u.uy - dy);
  149.     if(mon = m_at(u.ux, u.uy)) {
  150.         You("bump into %s.", a_monnam(mon));
  151.         wakeup(mon);
  152.         if(Is_airlevel(&u.uz))
  153.         mnexto(mon);
  154.         else {
  155.         /* sorry, not ricochets */
  156.         u.ux -= dx;
  157.         u.uy -= dy;
  158.         }
  159.         range = 0;
  160.     }
  161.  
  162.     newsym(u.ux, u.uy);
  163.  
  164.     if(range) {
  165.         flush_screen(1);
  166.         delay_output();
  167.     }
  168.     }
  169. }
  170.  
  171. static void
  172. check_shop_obj(obj, x, y, broken)
  173. register struct obj *obj;
  174. register xchar x, y;
  175. register boolean broken;
  176. {
  177.     register struct monst *shkp = 
  178.             shop_keeper(*in_rooms(u.ux, u.uy, SHOPBASE));
  179.  
  180.     if(!shkp) return;
  181.     if(!inside_shop(u.ux, u.uy)) return;
  182.  
  183.     if(broken) {
  184.             if(obj->unpaid) {
  185.             (void)stolen_value(obj, u.ux, u.uy, 
  186.                  (shkp && shkp->mpeaceful), FALSE);
  187.             subfrombill(obj, shkp);
  188.         }
  189.         return;
  190.     }
  191.  
  192.         if(!costly_spot(x, y) ||
  193.                *in_rooms(u.ux, u.uy, 0) != *in_rooms(x, y, 0)) { 
  194.             if(!inside_shop(x, y) && obj->unpaid) {
  195.             (void)stolen_value(obj, u.ux, u.uy, 
  196.                  (shkp && shkp->mpeaceful), FALSE);
  197.             subfrombill(obj, shkp);
  198.         }
  199.     } else
  200.             if(costly_spot(u.ux, u.uy) && costly_spot(x, y)) {
  201.             if(obj->unpaid) subfrombill(obj, shkp);
  202.             else if(!(x == shkp->mx && y == shkp->my))
  203.                     sellobj(obj, x, y);
  204.         }
  205. }
  206.  
  207.  
  208. int
  209. throwit(obj)
  210. register struct obj *obj;
  211. {
  212.     register struct monst *mon;
  213.     register int range, urange;
  214.     boolean impaired = (Confusion || Stunned || Blind ||
  215.                Hallucination || Fumbling);
  216.     int do_death = 0;
  217.  
  218.     if (obj->cursed && (u.dx || u.dy) && !rn2(7)) {
  219.         boolean slipok = TRUE;
  220.         if ((obj->oclass == WEAPON_CLASS || obj->oclass == GEM_CLASS)
  221.         && uwep && (objects[obj->otyp].w_propellor > 0) &&
  222.         (objects[obj->otyp].w_propellor ==
  223.                                              -objects[uwep->otyp].w_propellor))
  224.         pline("The %s misfires!", xname(obj));
  225.         else {
  226.         /* only slip if it's meant to be thrown */
  227.         if((obj->otyp >= DART && obj->otyp <= JAVELIN) ||
  228.            (obj->otyp >= DAGGER && obj->otyp <= CRYSKNIFE &&
  229.             obj->otyp != ATHAME) || obj->otyp == WAR_HAMMER)
  230.             pline("The %s slips as you throw it!", xname(obj));
  231.         else slipok = FALSE;
  232.         }
  233.         if (slipok) {
  234.         u.dx = rn2(3)-1;
  235.         u.dy = rn2(3)-1;
  236.         if (!u.dx && !u.dy) u.dz = 1;
  237.         impaired = TRUE;
  238.         }
  239.     }
  240.  
  241.     if(u.uswallow) {
  242.         mon = u.ustuck;
  243.         bhitpos.x = mon->mx;
  244.         bhitpos.y = mon->my;
  245.     } else if(u.dz) {
  246.       if (u.dz < 0 && pl_character[0] == 'V' &&
  247.           obj->oartifact == ART_MJOLLNIR && !impaired) {
  248.           pline("%s hits the ceiling and returns to your hand!",
  249.             The(xname(obj)));
  250.           obj = addinv(obj);
  251.           setuwep(obj);
  252.           return(1);
  253.       }
  254.       if (u.dz < 0 && !Is_airlevel(&u.uz) && !Underwater && !Is_waterlevel(&u.uz)) {
  255.         pline("%s hits the ceiling, then falls back on top of your %s.",
  256.         Doname2(obj),        /* note: obj->quan == 1 */
  257.         body_part(HEAD));
  258.         if(obj->oclass == POTION_CLASS)
  259.         potionhit(&youmonst, obj);
  260.         else {
  261.             int dmg = rnd((int)(obj->owt));
  262.           
  263.         if (uarmh) {
  264.             if(is_metallic(uarmh)) {
  265.                 pline("Fortunately, you are wearing a hard helmet.");
  266.             dmg = 1;
  267.             } else if (flags.verbose)
  268.                 Your("%s does not protect you.", xname(uarmh));
  269.         } else if (obj->otyp == CORPSE &&
  270.                 obj->corpsenm == PM_COCKATRICE) {
  271. #ifdef POLYSELF
  272.             if(!resists_ston(uasmon))
  273.             if(!(poly_when_stoned(uasmon) &&
  274.                     polymon(PM_STONE_GOLEM))) {
  275. #endif
  276.             killer = doname(obj);
  277.             You("turn to stone.");
  278.             do_death = STONING;
  279. #ifdef POLYSELF
  280.             }
  281. #endif
  282.         }
  283.  
  284.         if (!breaks(obj, TRUE)) {
  285.             if(!ship_object(obj, u.ux, u.uy, FALSE)) {
  286.             dropy(obj);
  287.             if(*u.ushops)
  288.                 check_shop_obj(obj, obj->ox, obj->oy, FALSE);
  289.             }
  290.         }
  291.         if (do_death == STONING)
  292.             done(STONING);
  293.         else
  294.             losehp(dmg, "falling object", KILLED_BY_AN);
  295.         }
  296.       } else hitfloor(obj);
  297.       return(1);
  298.  
  299.     } else if(obj->otyp == BOOMERANG && !Underwater) {
  300.         if(Is_airlevel(&u.uz) || Levitation) hurtle(-u.dx, -u.dy, 1);
  301.         mon = boomhit(u.dx, u.dy);
  302.         if(mon == &youmonst) {        /* the thing was caught */
  303.             exercise(A_DEX, TRUE);
  304.             (void) addinv(obj);
  305.             return(1);
  306.         }
  307.     } else {
  308.         urange = (int)(ACURRSTR)/2;
  309.         range = urange - (int)(obj->owt/40);
  310.         if (obj == uball) {
  311.             if (u.ustuck) range = 1;
  312.             else if (range >= 5) range = 5;
  313.         }
  314.         if (range < 1) range = 1;
  315.  
  316.         if ((obj->oclass == WEAPON_CLASS || obj->oclass == GEM_CLASS)
  317.                     && uwep && objects[obj->otyp].w_propellor) {
  318.             if (objects[obj->otyp].w_propellor ==
  319.                                  -objects[uwep->otyp].w_propellor)
  320.             range++;
  321.             else
  322.             range /= 2;
  323.         }
  324.  
  325.         if (Is_airlevel(&u.uz) || Levitation) {
  326.             /* action, reaction... */
  327.             urange -= range;
  328.             if(urange < 1) urange = 1;
  329.             range -= urange;
  330.             if(range < 1) range = 1;
  331.         }
  332.  
  333. #ifdef POLYSELF
  334.         if (obj->otyp == BOULDER) range = 20;
  335. #endif
  336.         if (obj == uball && u.utrap && u.utraptype == TT_INFLOOR)
  337.             range = 1;
  338.  
  339.         if (Underwater) range = 1;
  340.  
  341.         mon = bhit(u.dx,u.dy,range,THROWN_WEAPON,
  342.                (int (*)()) 0,(int (*)()) 0,obj);
  343.  
  344.         /* have to do this after bhit() so u.ux & u.uy are correct */
  345.         if(Is_airlevel(&u.uz) || Levitation)
  346.             hurtle(-u.dx, -u.dy, urange);
  347.     }
  348.     if(mon) {
  349.         if(mon->isshk && (!inside_shop(u.ux, u.uy) ||
  350.            !index(in_rooms(mon->mx, mon->my, SHOPBASE), *u.ushops))) { 
  351.             if(obj->otyp == PICK_AXE) {
  352.                 register struct obj *otmp;
  353.  
  354.             /* check if the pick axe was caught through  */
  355.             /* a successful call to shkcatch() in bhit() */
  356.                     for (otmp = mon->minvent; otmp; otmp = otmp->nobj)
  357.                      if (otmp == obj) return(1);
  358.             }
  359.             wakeup(mon);
  360.             hot_pursuit(mon);
  361.         }
  362.         (void) snuff_candle(obj);
  363.         /* awake monster if sleeping */
  364.         wakeup(mon);
  365.         notonhead = (bhitpos.x != mon->mx || bhitpos.y != mon->my);
  366.         if(thitmonst(mon, obj)) return(1);
  367.     }
  368.     if(!u.uswallow) {
  369.         /* the code following might become part of dropy() */
  370.         int obj_glyph = obj_to_glyph(obj);
  371.         boolean gone = FALSE;
  372.  
  373.         if (obj->oartifact == ART_MJOLLNIR && pl_character[0] == 'V') {
  374.             /* we must be wearing Gauntlets of Power to get here */
  375.             int x = bhitpos.x - u.dx, y = bhitpos.y - u.dy;
  376.  
  377.             tmp_at(DISP_FLASH, obj_glyph);
  378.             while(x != u.ux || y != u.uy) {
  379.             tmp_at(x, y);
  380.             delay_output();
  381.             x -= u.dx; y -= u.dy;
  382.             }
  383.             tmp_at(DISP_END, 0);
  384.  
  385.             if(!impaired) {
  386.             pline("%s returns to your hand!", The(xname(obj)));
  387.             obj = addinv(obj);
  388.             setuwep(obj);
  389.             if(cansee(bhitpos.x, bhitpos.y))
  390.                 newsym(bhitpos.x,bhitpos.y);
  391.             } else {
  392.             int dmg = rnd(4);
  393.             if (Blind)
  394.                 pline("%s hits your %s!",
  395.                   The(xname(obj)), body_part(ARM));
  396.             else
  397.                 pline("%s flies back toward you, hitting your %s!",
  398.                   The(xname(obj)), body_part(ARM));
  399.             (void) artifact_hit((struct monst *) 0, &youmonst,
  400.                         obj, &dmg, 0);
  401.             losehp(dmg, xname(obj), KILLED_BY);
  402.             if(ship_object(obj, u.ux, u.uy, FALSE)) 
  403.                     return (1);
  404.             dropy(obj);
  405.             }
  406.             return (1);
  407.         }
  408.         if (!IS_SOFT(levl[bhitpos.x][bhitpos.y].typ) && !u.uinwater &&
  409.             obj->oclass == POTION_CLASS && rn2(2)) {
  410.             if(distu(bhitpos.x, bhitpos.y) < 3 && rn2(5)) {
  411.             pline("The flask breaks, and you smell a peculiar odor...");
  412.             potionbreathe(obj);
  413.             } else if(!Blind)
  414.             pline("The flask breaks.");
  415.             else pline("Crash!");
  416.             if(*u.ushops)
  417.                 check_shop_obj(obj, bhitpos.x, bhitpos.y, TRUE);
  418.             obfree(obj, (struct obj *)0);
  419.             gone = TRUE;
  420.         }
  421.         if (gone || (!IS_SOFT(levl[bhitpos.x][bhitpos.y].typ) &&
  422.                  breaks(obj, TRUE))) {
  423.             tmp_at(DISP_FLASH, obj_glyph);
  424.             tmp_at(bhitpos.x, bhitpos.y);
  425.             delay_output();
  426.             tmp_at(DISP_END, 0);
  427.             return(1);
  428.         }
  429.         if(flooreffects(obj,bhitpos.x,bhitpos.y,"fall")) return(1);
  430.         if(obj->otyp == CRYSKNIFE)
  431.             obj->otyp = WORM_TOOTH;
  432.             if(mon && mon->isshk && obj->otyp == PICK_AXE) {
  433.                 mpickobj(mon, obj);
  434.             if(*u.ushops)
  435.                 check_shop_obj(obj, bhitpos.x, bhitpos.y, FALSE);
  436.             return(1);
  437.         }
  438.         (void) snuff_candle(obj);
  439.         if(!mon && obj != uball) {
  440.             if(ship_object(obj, bhitpos.x, bhitpos.y, FALSE))
  441.                 return(1);
  442.         }
  443.         obj->nobj = fobj;
  444.         fobj = obj;
  445.         place_object(obj, bhitpos.x, bhitpos.y);
  446.         if(*u.ushops && obj != uball)
  447.             check_shop_obj(obj, bhitpos.x, bhitpos.y, FALSE);
  448.         stackobj(obj);
  449.         if (obj == uball) drop_ball(bhitpos.x, bhitpos.y);
  450.         if(cansee(bhitpos.x, bhitpos.y)) newsym(bhitpos.x,bhitpos.y);
  451.     } else {
  452.         /* ball is not picked up by monster */
  453.         if (obj != uball) mpickobj(u.ustuck,obj);
  454.     }
  455.     return(1);
  456. }
  457.  
  458. int
  459. thitmonst(mon, obj)
  460. register struct monst *mon;
  461. register struct obj   *obj;
  462. {
  463.     register int    tmp; /* Base chance to hit */
  464.     register int    disttmp; /* distance modifier */
  465.  
  466.     /* Differences from melee weapons:
  467.      *
  468.      * Dex still gives a bonus, but strength does not.
  469.      * Polymorphed players lacking attacks may still throw.
  470.      * There's a base -1 to hit.
  471.      * No bonuses for fleeing or stunned targets (they don't dodge
  472.      *    melee blows as readily, but dodging arrows is hard anyway).
  473.      * Not affected by traps, etc.
  474.      * Certain items which don't in themselves do damage ignore tmp.
  475.      * Distance and monster size affect chance to hit.
  476.      */
  477.     tmp = -1 + Luck + find_mac(mon);
  478. #ifdef POLYSELF
  479.     if (u.umonnum >= 0) tmp += uasmon->mlevel;
  480.     else
  481. #endif
  482.         tmp += u.ulevel;
  483.     if(ACURR(A_DEX) < 4) tmp -= 3;
  484.     else if(ACURR(A_DEX) < 6) tmp -= 2;
  485.     else if(ACURR(A_DEX) < 8) tmp -= 1;
  486.     else if(ACURR(A_DEX) >= 14) tmp += (ACURR(A_DEX) - 14);
  487.  
  488.     /* modify to-hit depending on distance; but keep it sane */
  489.     disttmp = 3 - distmin(u.ux, u.uy, mon->mx, mon->my);
  490.     if(disttmp < -4) disttmp = -4;
  491.     tmp += disttmp;
  492.  
  493.     /* it's easier to hit a larger target */
  494.     if(bigmonst(mon->data)) tmp++;
  495.  
  496.     if(mon->msleep) {
  497.         mon->msleep = 0;
  498.         tmp += 2;
  499.     }
  500.     if(!mon->mcanmove || !mon->data->mmove) {
  501.         tmp += 4;
  502.         if(!rn2(10)) {
  503.             mon->mcanmove = 1;
  504.             mon->mfrozen = 0;
  505.         }
  506.     }
  507.     if (is_orc(mon->data) && pl_character[0]=='E') tmp++;
  508.     if (u.uswallow && mon == u.ustuck) tmp += 1000; /* Guaranteed hit */
  509.  
  510.     if(obj->oclass == GEM_CLASS && mon->data->mlet == S_UNICORN) {
  511.         if (mon->mtame) {
  512.             pline("%s catches and drops %s.",
  513.                 Monnam(mon), the(xname(obj)));
  514.             return(0);
  515.         } else {
  516.             pline("%s catches %s.", Monnam(mon), the(xname(obj)));
  517.             return(gem_accept(mon, obj));
  518.         }
  519.     }
  520.     if(obj->oclass == WEAPON_CLASS || obj->otyp == PICK_AXE ||
  521.        obj->otyp == UNICORN_HORN || obj->oclass == GEM_CLASS) {
  522.         if(obj->otyp < DART || obj->oclass == GEM_CLASS) {
  523.             if (!uwep ||
  524.             objects[obj->otyp].w_propellor !=
  525.             -objects[uwep->otyp].w_propellor) {
  526.             tmp -= 4;
  527.             } else {
  528.             tmp += uwep->spe - uwep->oeroded;
  529.             /*
  530.              * Elves and Samurais are highly trained w/bows,
  531.              * especially their own special types of bow.
  532.              * Polymorphing won't make you a bow expert.
  533.              */
  534.             if ((pl_character[0] == 'E' || pl_character[0] == 'S')
  535.                  && -objects[uwep->otyp].w_propellor == WP_BOW)
  536.                 tmp++;
  537.             if (pl_character[0] == 'E' && uwep->otyp == ELVEN_BOW)
  538.                 tmp++;
  539.             if (pl_character[0] == 'S' && uwep->otyp == YUMI)
  540.                 tmp++;
  541.             }
  542.         } else if(obj->otyp == BOOMERANG) tmp += 4;
  543.         tmp += obj->spe;
  544.         tmp += hitval(obj, mon->data);
  545.         if(tmp >= rnd(20)) {
  546.             if(hmon(mon,obj,1)){
  547.               /* mon still alive */
  548.               cutworm(mon, bhitpos.x, bhitpos.y, obj);
  549.             }
  550.             exercise(A_DEX, TRUE);
  551.             /* projectiles thrown disappear sometimes */
  552.             if((obj->otyp < BOOMERANG || obj->oclass == GEM_CLASS)
  553.                                 && rn2(3)) {
  554.                     if(*u.ushops)
  555.                              check_shop_obj(obj, bhitpos.x, 
  556.                                    bhitpos.y, TRUE);
  557.                 /* check bill; free */
  558.                 obfree(obj, (struct obj *)0);
  559.                 return(1);
  560.             }
  561.         } else miss(xname(obj), mon);
  562.     } else if(obj->otyp == HEAVY_IRON_BALL) {
  563.         if(obj != uball) tmp += 2;
  564.         exercise(A_STR, TRUE);
  565.         if(tmp >= rnd(20)) {
  566.             (void) hmon(mon,obj,1);
  567.             exercise(A_DEX, TRUE);
  568.         } else miss(xname(obj), mon);
  569.     } else if (obj->otyp == BOULDER) {
  570.         tmp += 6;  /* Likely to hit! */
  571.         exercise(A_STR, TRUE);
  572.         if(tmp >= rnd(20)) {
  573.             (void) hmon(mon,obj,1);
  574.             exercise(A_DEX, TRUE);
  575.         } else miss(xname(obj), mon);
  576.     } else if((obj->otyp == CREAM_PIE
  577. #ifdef POLYSELF
  578.             || obj->otyp == BLINDING_VENOM
  579. #endif
  580.                     ) && ACURR(A_DEX) >= rnd(10)) {
  581.         (void) hmon(mon,obj,1); /* can't die from it */
  582. #ifdef POLYSELF
  583.     } else if(obj->otyp == ACID_VENOM && ACURR(A_DEX) >= rnd(10)) {
  584.         (void) hmon(mon,obj,1);
  585. #endif
  586.     } else if(obj->oclass == POTION_CLASS && ACURR(A_DEX) >= rnd(15)) {
  587.         potionhit(mon, obj);
  588.         return(1);
  589.     } else {
  590.         pline("%s misses %s.", The(xname(obj)), mon_nam(mon));
  591.         if(obj->oclass == FOOD_CLASS && is_domestic(mon->data))
  592.             if(tamedog(mon,obj)) return(1);
  593.     }
  594.     return(0);
  595. }
  596.  
  597. static int
  598. gem_accept(mon, obj)
  599. register struct monst *mon;
  600. register struct obj *obj;
  601. {
  602.     char buf[BUFSZ];
  603.     boolean is_buddy = sgn(mon->data->maligntyp) == sgn(u.ualign.type);
  604.     boolean is_gem = objects[obj->otyp].oc_material == GEMSTONE;
  605.     int ret = 0;
  606.     static const char NEARDATA nogood[] = " is not interested in your junk.";
  607.     static const char NEARDATA acceptgift[] = " accepts your gift.";
  608.     static const char NEARDATA maybeluck[] = " hesitatingly";
  609.     static const char NEARDATA noluck[] = " graciously";
  610.     static const char NEARDATA addluck[] = " gratefully";
  611.  
  612.     Strcpy(buf,Monnam(mon));
  613.  
  614.     mon->mpeaceful = 1;
  615.  
  616.     /* object properly identified */
  617.     if(obj->dknown && objects[obj->otyp].oc_name_known) {
  618.         if(is_gem) {
  619.             if(is_buddy) {
  620.                 Strcat(buf,addluck);
  621.                 change_luck(5);
  622.             } else {
  623.                 Strcat(buf,maybeluck);
  624.                 change_luck(rn2(7)-3);
  625.             }
  626.         } else {
  627.             Strcat(buf,nogood);
  628.             goto nopick;
  629.         }
  630.     /* making guesses */
  631.     } else if(obj->onamelth || objects[obj->otyp].oc_uname) {
  632.         if(is_gem) {
  633.             if(is_buddy) {
  634.                 Strcat(buf,addluck);
  635.                 change_luck(2);
  636.             } else {
  637.                 Strcat(buf,maybeluck);
  638.                 change_luck(rn2(3)-1);
  639.             }
  640.         } else {
  641.             Strcat(buf,nogood);
  642.             goto nopick;
  643.         }
  644.     /* value completely unknown to @ */
  645.     } else {
  646.         if(is_gem) {
  647.             if(is_buddy) {
  648.                 Strcat(buf,addluck);
  649.                 change_luck(1);
  650.             } else {
  651.                 Strcat(buf,maybeluck);
  652.                 change_luck(rn2(3)-1);
  653.             }
  654.         } else {
  655.             Strcat(buf,noluck);
  656.         }
  657.     }
  658.      Strcat(buf,acceptgift);
  659.     mpickobj(mon, obj);
  660.     if(*u.ushops) check_shop_obj(obj, mon->mx, mon->my, TRUE);
  661.     ret = 1;
  662.  
  663. nopick:
  664.     if(!Blind) pline(buf);
  665.     rloc(mon);
  666.     return(ret);
  667. }
  668.  
  669. /* returns 0 if object doesn't break    */
  670. /* returns 1 if object broke         */
  671. int
  672. breaks(obj, loose)
  673. register struct obj   *obj;
  674. register boolean loose;        /* if not loose, obj is in fobj chain */
  675. {
  676.     switch(obj->otyp) {
  677.         case MIRROR:
  678.             change_luck(-2);    /* and fall through */
  679.         case CRYSTAL_BALL:
  680. #ifdef TOURIST
  681.         case EXPENSIVE_CAMERA:
  682. #endif
  683.             if(!Blind)
  684.                 pline("%s shatters into a thousand pieces!",
  685.                 Doname2(obj));
  686.             else You("hear something shatter!");
  687.             break;
  688.         case EGG:
  689.             pline("Splat!");
  690.             break;
  691.         case CREAM_PIE:
  692.             pline("What a mess!");
  693.             break;
  694.         case ACID_VENOM:
  695.         case BLINDING_VENOM:
  696.             pline("Splash!");
  697.             break;
  698.         default:
  699.             return 0;
  700.     }
  701.  
  702.     /* it is currently assumed that 'loose' is co-extensive
  703.      * with 'thrown'.  if this changes, an explicit 'thrown'
  704.      * arg must be added to breaks() to ensure proper 
  705.      * treatment of shop objs.
  706.      */
  707.     if(loose) {
  708.         newsym(obj->ox,obj->oy);
  709.         if(*u.ushops) 
  710.                 check_shop_obj(obj, obj->ox, obj->oy, TRUE);
  711.         obfree(obj, (struct obj *)0);
  712.     } else {
  713.             /* it is assumed that the obj is a floor-object */ 
  714.             register struct monst *shkp;
  715.             boolean costly, insider;
  716.         long loss = 0L;
  717.  
  718. #ifdef GCC_WARN
  719.         shkp = (struct monst *) 0;
  720. #endif
  721.  
  722.         costly = (costly_spot(obj->ox, obj->oy) && 
  723.                    (shkp = shop_keeper(*in_rooms(obj->ox,
  724.                   obj->oy, SHOPBASE))) != (struct monst *)0);
  725.         insider = (*u.ushops && inside_shop(u.ux, u.uy) &&
  726.              *in_rooms(obj->ox, obj->oy, SHOPBASE) == *u.ushops);
  727.  
  728.         if(costly)
  729.             loss = stolen_value(obj, u.ux, u.uy, 
  730.                  (shkp && shkp->mpeaceful), FALSE);
  731.         if(loss && !insider)
  732.             make_angry_shk(shkp, obj->ox, obj->oy);
  733.  
  734.         delobj(obj);
  735.     }
  736.     return(1);
  737. }
  738.  
  739. /*
  740.  *  Note that the gold object is *not* attached to the fobj chain.
  741.  */
  742. static int
  743. throw_gold(obj)
  744. struct obj *obj;
  745. {
  746.     int range, odx, ody;
  747.     long zorks = obj->quan;
  748.     register struct monst *mon;
  749.  
  750.     if(u.uswallow) {
  751.         pline(is_animal(u.ustuck->data) ?
  752.             "%s in the %s's entrails." : "%s into %s.",
  753.             "The gold disappears", mon_nam(u.ustuck));
  754.         u.ustuck->mgold += zorks;
  755.         dealloc_obj(obj);
  756.         return(1);
  757.     }
  758.  
  759.     if(u.dz) {
  760.           if(u.dz < 0 && !Is_airlevel(&u.uz) && !Underwater && !Is_waterlevel(&u.uz)) {
  761.     pline("The gold hits the ceiling, then falls back on top of your %s.",
  762.             body_part(HEAD));
  763.             /* some self damage? */
  764.             if(uarmh) pline("Fortunately, you are wearing a helmet!");
  765.         }
  766.         if(flooreffects(obj,u.ux,u.uy,"fall")) return(1);
  767.         if(u.dz > 0) pline("The gold hits the floor.");
  768.         obj->nobj = fobj;    /* add the gold to the object list */
  769.         fobj = obj;
  770.         place_object(obj,u.ux,u.uy);
  771.                 if(*u.ushops) sellobj(obj, u.ux, u.uy);
  772.         stackobj(obj);
  773.         newsym(u.ux,u.uy);
  774.         return 1;
  775.     }
  776.  
  777.     /* consistent with range for normal objects */
  778.     range = (int)((ACURRSTR)/2 - obj->owt/40);
  779.  
  780.     /* see if the gold has a place to move into */
  781.     odx = u.ux + u.dx;
  782.     ody = u.uy + u.dy;
  783.     if(!ZAP_POS(levl[odx][ody].typ) || closed_door(odx, ody)) {
  784.         bhitpos.x = u.ux;
  785.         bhitpos.y = u.uy;
  786.     } else {
  787.         mon = bhit(u.dx, u.dy, range, THROWN_WEAPON,
  788.                    (int (*)()) 0, (int (*)()) 0, obj);
  789.         if(mon) {
  790.             if (ghitm(mon, obj))    /* was it caught? */
  791.             return 1;
  792.         } else {
  793.             if(ship_object(obj, bhitpos.x, bhitpos.y, FALSE)) 
  794.                 return 1;
  795.         }
  796.     }
  797.  
  798.     if(flooreffects(obj,bhitpos.x,bhitpos.y,"fall")) return(1);
  799.     obj->nobj = fobj;    /* add the gold to the object list */
  800.     fobj = obj;
  801.     place_object(obj,bhitpos.x,bhitpos.y);
  802.         if(*u.ushops) sellobj(obj, bhitpos.x, bhitpos.y);
  803.     stackobj(obj);
  804.     newsym(bhitpos.x,bhitpos.y);
  805.     return(1);
  806. }
  807.  
  808. /*dothrow.c*/
  809.